package arkham.data;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import arkham.data.Globals.EffectUsage;
import arkham.data.Investigator.InvestigatorPower;
import arkham.jaxb.encounter.ModEffectType;
import arkham.util.AHLogger;

/**
 * A mod-effect is a modifier that applies to an investigator as a result
 * of his intrinsic abilities, or granted by an item.
 * <br>
 * The following properties are defined for a mod-effect
 * @author ctheng
 *
 */
public class ModEffect extends Effect
{
    private final static Pattern BEFORE_CHECK_PATTERN = Pattern.compile("Before (\\w+) Check");
    private final static Pattern DURING_CHECK_PATTERN = Pattern.compile("During (\\w+) Check");
    private String type;
    private String details;
    private String amount;

    public ModEffect(String type, String details, String amount)
    {
        super();
        usage = EffectUsage.CHOICE;
        this.type = type;
        this.details = details;
        this.amount = amount;
    }

    /**
     * @return the type
     */
    public String getType() {
        return type;
    }

    /**
     * @return the details
     */
    public String getDetails() {
        return details;
    }

    /**
     * @return the amount
     */
    public String getAmount() {
        return amount;
    }

    /**
     * Gets the amount as an int, or 0 if not an int.
     * @return the amount as integer
     */
    public int getAmountAsInt()
    {
        try
        {
            return Integer.parseInt(amount);
        }
        catch (NumberFormatException e)
        {
            return 0;
        }
    }

    /*
     * (non-Javadoc)
     * @see arkham.data.Effect#getIdentifier()
     */
    @Override
    public String getIdentifier()
    {
        return getSourceString() + "," + type + "," + details;
    }

    @Override
    public String toString()
    {
        return type + "," + details + (amount == null ? "" : "," + amount);
    }

    /**
     * Gets the string to be shown on the dropdown menu
     * @return the display string
     */
    public String getDisplayString()
    {
        return source.getName() + ": " + getDescription(this);
    }

    /**
     * Creates the data representation of the mod effect from the XML info
     * and performs a stringent validation check to make sure the XML data is
     * valid.
     * <br>Will return <b>null</b> on a failure.
     *
     * @param xmleffect the XML effect info
     * @return the data representation of the mod effect
     */
    public static ModEffect createModEffectFromXml(ModEffectType xmleffect)
    {
        ModEffect mod = new ModEffect(xmleffect.getType(),
                xmleffect.getDetails(), xmleffect.getAmount());
        boolean valid = EffectUsage.assignUsage(mod, xmleffect.getUsage());
        if (!valid)
        {
            AHLogger.error("Invalid usage string on temp effect: " + xmleffect.getUsage());
            return null;
        }
        mod.getExtraCosts().addAll(xmleffect.getExtraCost());
        return mod;
    }

    /**
     * Gets the description of this mod effect to be displayed to the user
     * @return the description
     */
    public static String getDescription(ModEffect mod)
    {
        Matcher mt;
        if (mod.getType().equals("Prevent Damage"))
        {
            if (mod.getDetails().equals("Stamina"))
            {
                if (mod.getAmount().equals("=All"))
                {
                    return "Prevents all Stamina damage";
                }
                else
                {
                    return "Prevents " + mod.getAmount() + " Stamina damage";
                }
            }
        }
        else if (mod.getType().equals("Evade Monster"))
        {
            if (mod.getDetails().equals("Automatically Pass"))
            {
                return "Pass Evade check";
            }
        }
        else if ((mt = BEFORE_CHECK_PATTERN.matcher(mod.getType())).matches())
        {
            if (mod.getDetails().equals("Automatically Pass"))
            {
                return "Automatically pass";
            }
            else if (mod.getDetails().equals("Bonus Dice"))
            {
                return "+" + mod.getAmount() + " extra dice";
            }
            else if (mod.getDetails().equals("Flute of the Outer Gods"))
            {
                return "Defeat all monsters in area";
            }
        }
        else if ((mt = DURING_CHECK_PATTERN.matcher(mod.getType())).matches())
        {
            if (mod.getDetails().equals("Reroll All"))
            {
                return "Reroll all dice";
            }
            else if (mod.getDetails().equals("Reroll Dice"))
            {
                return "Reroll up to " + mod.getAmount() + " dice";
            }
        }
        else if (mod.getType().equals("Weapon"))
        {
            if (mod.getDetails().equals("Physical"))
            {
                return "+" + mod.getAmountAsInt() + " Combat Check (physical)";
            }
            else if (mod.getDetails().equals("Magical"))
            {
                return "+" + mod.getAmountAsInt() + " Combat Check (magical)";
            }
        }
        else if (mod.getType().equals("Combat Spell"))
        {
            if (mod.getDetails().equals("Combat Bonus"))
            {
                return "+" + mod.getAmountAsInt() + " Combat check until end of combat";
            }
            else if (mod.getDetails().equals("Automatically Pass"))
            {
                return "Automatically pass Combat Check";
            }
            else if (mod.getDetails().equals("Enchant Weapon"))
            {
                return "Makes a Physical weapon Magical";
            }
            else if (mod.getDetails().equals("Red Sign"))
            {
                return "Reduce toughness and negate an attribute";
            }
        }
        else if (mod.getType().equals("Special"))
        {
            if (mod.getDetails().equals("Redraw Location Card"))
            {
                return "Redraw location card";
            }
        }
        return "Unknown effect";
    }
}
